package com.hllxd.hism.star.basic.service.service;

import com.alibaba.fastjson.JSON;
import com.hllxd.hism.star.basic.service.dao.mapper.mis.DqcConfigMapper;
import com.hllxd.hism.star.basic.service.model.DqcCheckTaskConfigEntity;
import com.hllxd.hism.star.basic.service.model.DqcConfigEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * @author xiyong.lxy
 * @date 2022-03-13 16:51
 * 数据质量配置信息管理
 */
@Slf4j
@Service("dqcConfigService")
public class DqcConfigServiceImpl implements DqcConfigService {

    @Autowired
    private DqcConfigMapper dqcConfigMapper;

    @Override
    public List<DqcConfigEntity> listDqcConfig() {
        return dqcConfigMapper.listDqcConfig();
    }

    @Override
    public DqcConfigEntity getDqcConfig(Long id) {
        return dqcConfigMapper.getDqcConfig(id);
    }

    @Override
    public Long setDqcConfig(DqcConfigEntity entity) {
        entity.setTaskId(entity.getTaskId() != null ? entity.getTaskId() : "");
        entity.setTag(entity.getTag() != null ? entity.getTag() : "");
        entity.setUserName(entity.getUserName() != null ? entity.getUserName() : "");
        entity.setTableLevel(entity.getTableLevel() != null ? entity.getTableLevel() : "");
        entity.setTableName(entity.getTableName() != null ? entity.getTableName() : "");
        entity.setPath(entity.getPath() != null ? entity.getPath() : "");
        entity.setPartition(entity.getPartition() != null ? entity.getPartition() : "");
        entity.setIsTest(entity.getIsTest() != null ? entity.getIsTest() : 1);
        entity.setTaskDesc(entity.getTaskDesc() != null ? entity.getTaskDesc() : "");
        log.info("set param: {}", JSON.toJSONString(entity));
        if (entity.id == null || entity.id == 0) {
            return dqcConfigMapper.insertDqcConfig(entity);
        } else {
            return dqcConfigMapper.updateDqcConfig(entity);
        }
    }

    @Override
    public Long delDqcConfig(Long id) {
        return dqcConfigMapper.updateDqcConfigAction(id);
    }

    @Override
    public List<DqcCheckTaskConfigEntity> listDqcCheckTaskConfig() {
        return dqcConfigMapper.listDqcCheckTaskConfig();
    }

    @Override
    public int setDqcCheckTaskConfig(DqcCheckTaskConfigEntity aa) {
        DqcCheckTaskConfigEntity entity = generateCheckSql(aa, null);
        if (aa.getId() != null && aa.getId() > 0) {
            return dqcConfigMapper.updateByPrimaryKeySelective(entity);
        } else {
            return dqcConfigMapper.insertSelective(entity);
        }
    }

    @Override
    public DqcCheckTaskConfigEntity getDqcCheckTaskConfig(DqcCheckTaskConfigEntity aa) {
        return dqcConfigMapper.getDqcCheckTaskConfig(aa.getId());
    }

    @Override
    public int setDqcCheckTaskStatus(Long id, Integer isOpen) {
        DqcCheckTaskConfigEntity aa = new DqcCheckTaskConfigEntity();
        aa.setIsOpen(isOpen);
        aa.setId(id);
        return dqcConfigMapper.updateByPrimaryKeySelective(aa);
    }

    @Override
    public DqcCheckTaskConfigEntity generateCheckSql(DqcCheckTaskConfigEntity aa, LocalDate localDate) {
        String taskType = aa.getTaskType();
        String checkSql = "";
        switch (taskType.toUpperCase()) {
//            case "SLA_CHECK":
//                return generateSLACheckSql(aa);
            case "DATA_COUNT_CHECK":
                checkSql = generateDataCountCheckSql(aa, localDate);
                break;
            case "JOIN_RADIO_CHECK":
                checkSql = generateJoinRadioCheckSql(aa, localDate);
                break;
            case "FIELD_ERROR_CHECK":
                checkSql = generateFieldErrorCheckSql(aa, localDate);
                break;
            default:
                checkSql = "";
                break;
        }
        aa.setCheckSql(checkSql);
        return aa;
    }

    private String generateFieldErrorCheckSql(DqcCheckTaskConfigEntity aa, LocalDate localDate) {
        String t_1 = "${#date(0,0,-1):yyyyMMdd#}";
        if (localDate != null) {
            t_1 = localDate.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        }
        String str = "SELECT  SUM(" + aa.getFieldCheckRule() + ") as field_error_count\n" +
                "       ,COUNT(*) as table_count\n" +
                "FROM " + aa.getCheckTable() + "\n" +
                "WHERE dt = '" + t_1 + "'";
        return str;
    }

    private String generateJoinRadioCheckSql(DqcCheckTaskConfigEntity aa, LocalDate localDate) {
        String t_1 = "${#date(0,0,-1):yyyyMMdd#}";
        if (localDate != null) {
            t_1 = localDate.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        }
        StringBuilder sb = new StringBuilder();
        sb.append("SELECT  COUNT(b.*) AS compare_table_join_col_count\n")
                .append("       ,SUM(case WHEN a.").append(aa.getJoinField()).append(" is null THEN 0 else 1 end ) check_table_join_col_count\n")
                .append("FROM ")
                .append(aa.getCompareTable()).append(" b\n")
                .append("LEFT JOIN ")
                .append(aa.getCheckTable()).append(" a\n")
                .append("ON a.").append(aa.getJoinField()).append(" = b.").append(aa.getJoinField()).append("\n")
                .append(" where a.dt=").append(t_1).append(" and b.dt=").append(t_1);
        return sb.toString();
    }


    private String generateDataCountCheckSql(DqcCheckTaskConfigEntity aa, LocalDate localDate) {
        String t_1 = "${#date(0,0,-1):yyyyMMdd#}";
        String w_1 = "${#date(0,0,-8):yyyyMMdd#}";
        String two_w_1 = "${#date(0,0,-15):yyyyMMdd#}";
        if (localDate != null) {
            t_1 = localDate.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
            w_1 = localDate.minusDays(7).format(DateTimeFormatter.ofPattern("yyyyMMdd"));
            two_w_1 = localDate.minusDays(14).format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        }

        StringBuilder sb = new StringBuilder()
                .append("SELECT  y.cnt\n")
                .append("       ,a.max_cnt\n")
                .append("       ,a.min_cnt\n")
                .append("       ,a.max_range\n")
                .append("       ,a.min_range\n")
                .append("       ,(y.cnt-a.max_range)/(a.max_range-a.min_range) AS max_threshold\n")
                .append("       ,(y.cnt-a.min_range)/(a.max_range-a.min_range) AS min_threshold\n")
                .append("FROM\n")
                .append("(\n")
                .append("    SELECT  COUNT(*) cnt\n")
                .append("    FROM ").append(aa.getCheckTable()).append("\n")
                .append("    WHERE dt = ").append(t_1).append(" \n")
                .append(") y\n")
                .append("INNER JOIN\n")
                .append("(\n")
                .append("    SELECT  \n")
                .append("        MAX(cnt) AS max_cnt,\n")
                .append("        MIN(cnt) AS min_cnt,\n")
                .append("        MAX(cnt)* 1.1 AS max_range,\n")
                .append("        MIN(cnt)* 0.9 AS min_range")
                .append("    FROM\n")
                .append("    (\n")
                .append("        SELECT  COUNT(*) AS cnt\n")
                .append("        FROM ").append(aa.getCheckTable()).append("\n")
                .append("        WHERE dt = ").append(w_1).append(" \n")
                .append("        UNION ALL\n")
                .append("        SELECT  COUNT(*) AS cnt\n")
                .append("        FROM ").append(aa.getCheckTable()).append("\n")
                .append("        WHERE dt = ").append(two_w_1).append(" \n")
                .append("    ) c\n")
                .append(")a\n")
                .append("ON 1 = 1");

        return sb.toString();
    }

//    private DqcCheckTaskConfigEntity generateSLACheckSql(DqcCheckTaskConfigEntity aa) {
//
//        String checkTable = aa.getCheckTable();
//        String produceTime = aa.getProduceTime();
//
//        StringBuilder sb = new StringBuilder();
//
//        return null;
//    }
}
